package com.rzt.cft.service.uc.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rzt.cft.constant.StatusConstant;
import com.rzt.cft.constant.TypeConstant;
import com.rzt.cft.utils.CustomUtil;
import com.rzt.cft.entity.project.ProjectDetail;
import com.rzt.cft.entity.project.ProjectOrder;
import com.rzt.cft.entity.uc.UcDistributionLog;
import com.rzt.cft.entity.uc.UcDistributionType;
import com.rzt.cft.entity.uc.UcRebateLog;
import com.rzt.cft.entity.uc.UcUser;
import com.rzt.cft.mapper.project.ProjectDetailMapper;
import com.rzt.cft.mapper.project.ProjectOrderMapper;
import com.rzt.cft.mapper.uc.UcDistributionLogMapper;
import com.rzt.cft.mapper.uc.UcDistributionTypeMapper;
import com.rzt.cft.mapper.uc.UcRebateLogMapper;
import com.rzt.cft.mapper.uc.UcUserMapper;
import com.rzt.cft.param.uc.InsertIntegralParam;
import com.rzt.cft.param.uc.InsertUsableParam;
import com.rzt.cft.param.uc.UcAssetStatisticsParam;
import com.rzt.cft.service.uc.IUcAssetService;
import com.rzt.cft.service.uc.IUcAssetStatisticsService;
import com.rzt.cft.service.uc.IUcRebateLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户-返利记录 服务实现类
 * </p>
 *
 * @author zhongzhong
 * @since 2020-03-16
 */
@Service
@Slf4j
public class UcRebateLogServiceImpl extends ServiceImpl<UcRebateLogMapper, UcRebateLog> implements IUcRebateLogService {

    @Autowired
    private ProjectOrderMapper projectOrderMapper;

    @Autowired
    private IUcAssetService ucAssetService;

    @Autowired
    private IUcAssetStatisticsService ucAssetStatisticsService;

    @Autowired
    private ProjectDetailMapper projectDetailMapper;

    @Autowired
    private UcUserMapper ucUserMapper;

    @Autowired
    private UcDistributionTypeMapper ucDistributionTypeMapper;

    @Autowired
    private UcDistributionLogMapper distributionLogMapper;

    @Override
    @Transactional
    public Boolean intelligenceRebate(ProjectOrder projectOrder) {
        //未完成返利的智能订单信息和项目信息
        QueryWrapper<UcRebateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_order_id", projectOrder.getId());
        queryWrapper.ge("create_at", LocalDateTime.of(LocalDate.now(), LocalTime.MIN));
        queryWrapper.le("create_at", LocalDateTime.of(LocalDate.now(), LocalTime.MAX));
        List<UcRebateLog> ucRebateLogs = baseMapper.selectList(queryWrapper);
        //如果已有当天订单返利，直接返回
        if (ucRebateLogs.size() > 0) {
            return false;
        }
        //判断是否最后一天
        Duration duration = Duration.between(projectOrder.getCompletionTime(), LocalDateTime.now());
        Long days = duration.toDays();
        log.info("days  : {}", days);
        if (duration.toDays() > 0) {
            //已经超期，修改状态为已完成
            projectOrder.setStatus(StatusConstant.ProjectOrderStatus.COMPLETED);
            projectOrderMapper.updateById(projectOrder);
            return false;
        }
        if (duration.toDays() == 0) {
            //先返回本金
            returnPrincipal(projectOrder);
            projectOrder.setStatus(StatusConstant.ProjectOrderStatus.COMPLETED);
            projectOrderMapper.updateById(projectOrder);
        }
        //判断是半年还是一年利率
        ProjectDetail projectDetail = projectDetailMapper.selectById(projectOrder.getProjectId());
        BigDecimal rate = projectOrder.getTerm().equals(TypeConstant.projectTerm.HALF_YEAR) ? projectDetail.getHalfYearRate() : projectDetail.getYearRate();
        BigDecimal amt = projectOrder.getAmount().multiply(rate).multiply(projectDetail.getCashRatio());
        BigDecimal integral = projectOrder.getAmount().multiply(rate).multiply(projectDetail.getIntegralRatio());

        //计算个人返利，生成返利订单，修改用户余额、统计等信息
        UcRebateLog ucRebateLog = new UcRebateLog();
        ucRebateLog.setAmt(amt);
        ucRebateLog.setTxnSsn(CustomUtil.getSsn());
        ucRebateLog.setProjectId(projectOrder.getProjectId());
        ucRebateLog.setProjectOrderId(projectOrder.getId());
        ucRebateLog.setUserId(projectOrder.getUserId());
        ucRebateLog.setType(TypeConstant.ucRebateType.INTELLIGENCE_REBATE);
        ucRebateLog.setIntegral(integral);
        baseMapper.insert(ucRebateLog);

        InsertUsableParam insertUsableParam = new InsertUsableParam();
        insertUsableParam.setRemarks(ucRebateLog.getId());
        insertUsableParam.setUserId(projectOrder.getUserId());
        insertUsableParam.setUsable(amt);
        insertUsableParam.setType(TypeConstant.usableChangeType.BALANCE_PROJECT_REBATE);
        ucAssetService.insertUsable(insertUsableParam);

        InsertIntegralParam insertIntegralParam = new InsertIntegralParam();
        insertIntegralParam.setUserId(projectOrder.getUserId());
        insertIntegralParam.setIntegral(integral);
        insertIntegralParam.setType(TypeConstant.integralChangeType.INTEGRAL_PROJECT_REBATE);
        insertIntegralParam.setRemarks(ucRebateLog.getId());
        ucAssetService.insertIntegral(insertIntegralParam);

        UcAssetStatisticsParam ucAssetStatisticsParam = new UcAssetStatisticsParam();
        ucAssetStatisticsParam.setUserId(projectOrder.getUserId());
        ucAssetStatisticsParam.setAccumulationIntegral(integral);
        ucAssetStatisticsParam.setAccumulationRebate(amt);
        ucAssetStatisticsService.addAssetStatistics(ucAssetStatisticsParam);

        //计算分销人员返利
        List<UcDistributionType> ucDistributionTypes = ucDistributionTypeMapper.selectList(null);
        Boolean result = distributionRebate(projectOrder, ucDistributionTypes, projectDetail);
        return result;
    }

    @Override
    @Transactional
    public Boolean optionalRebate(ProjectOrder projectOrder) {
        //未完成返利的智能订单信息和项目信息
        QueryWrapper<UcRebateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_order_id", projectOrder.getId());
        List<UcRebateLog> ucRebateLogs = baseMapper.selectList(queryWrapper);
        //如果已有订单返利，直接返回
        if (ucRebateLogs.size() > 0) {
            return false;
        }
        //先返回本金
        returnPrincipal(projectOrder);
        projectOrder.setStatus(StatusConstant.ProjectOrderStatus.COMPLETED);
        projectOrderMapper.updateById(projectOrder);
        //查询项目信息
        ProjectDetail projectDetail = projectDetailMapper.selectById(projectOrder.getProjectId());
        BigDecimal amt = projectOrder.getAmount().multiply(projectDetail.getDailyInverse()).multiply(projectDetail.getCashRatio());
        BigDecimal integral = projectOrder.getAmount().multiply(projectDetail.getDailyInverse()).multiply(projectDetail.getIntegralRatio());

        //计算个人返利，生成返利订单，修改用户余额、统计等信息
        UcRebateLog ucRebateLog = new UcRebateLog();
        ucRebateLog.setAmt(amt);
        ucRebateLog.setTxnSsn(CustomUtil.getSsn());
        ucRebateLog.setProjectId(projectOrder.getProjectId());
        ucRebateLog.setProjectOrderId(projectOrder.getId());
        ucRebateLog.setUserId(projectOrder.getUserId());
        ucRebateLog.setType(TypeConstant.ucRebateType.OPTIONAL_REBATE);
        ucRebateLog.setIntegral(integral);
        baseMapper.insert(ucRebateLog);

        InsertUsableParam insertUsableParam = new InsertUsableParam();
        insertUsableParam.setRemarks(ucRebateLog.getId());
        insertUsableParam.setUserId(projectOrder.getUserId());
        insertUsableParam.setUsable(amt);
        insertUsableParam.setType(TypeConstant.usableChangeType.BALANCE_PROJECT_REBATE);
        ucAssetService.insertUsable(insertUsableParam);

        InsertIntegralParam insertIntegralParam = new InsertIntegralParam();
        insertIntegralParam.setUserId(projectOrder.getUserId());
        insertIntegralParam.setIntegral(integral);
        insertIntegralParam.setType(TypeConstant.integralChangeType.INTEGRAL_PROJECT_REBATE);
        insertIntegralParam.setRemarks(ucRebateLog.getId());
        ucAssetService.insertIntegral(insertIntegralParam);

        UcAssetStatisticsParam ucAssetStatisticsParam = new UcAssetStatisticsParam();
        ucAssetStatisticsParam.setUserId(projectOrder.getUserId());
        ucAssetStatisticsParam.setAccumulationIntegral(integral);
        ucAssetStatisticsParam.setAccumulationRebate(amt);
        ucAssetStatisticsService.addAssetStatistics(ucAssetStatisticsParam);

        //计算分销人员返利
        List<UcDistributionType> ucDistributionTypes = ucDistributionTypeMapper.selectList(null);
        Boolean result = distributionRebate(projectOrder, ucDistributionTypes, projectDetail);
        return result;
    }

    public Boolean returnPrincipal(ProjectOrder projectOrder) {
        //添加返本记录
        UcRebateLog ucRebateLog = new UcRebateLog();
        ucRebateLog.setAmt(projectOrder.getAmount());
        ucRebateLog.setTxnSsn(CustomUtil.getSsn());
        ucRebateLog.setProjectId(projectOrder.getProjectId());
        ucRebateLog.setProjectOrderId(projectOrder.getId());
        ucRebateLog.setUserId(projectOrder.getUserId());
        ucRebateLog.setType(TypeConstant.ucRebateType.RETUR_CAPITAL);
        baseMapper.insert(ucRebateLog);

        InsertUsableParam insertUsableParam = new InsertUsableParam();
        insertUsableParam.setRemarks(ucRebateLog.getId());
        insertUsableParam.setFreeze(projectOrder.getAmount().negate());
        insertUsableParam.setUserId(projectOrder.getUserId());
        insertUsableParam.setInvestment(projectOrder.getAmount().negate());
        insertUsableParam.setUsable(projectOrder.getAmount());
        insertUsableParam.setType(TypeConstant.usableChangeType.BALANCE_RETUR_CAPITAL);
        Boolean result = ucAssetService.insertUsable(insertUsableParam);
        return result;
    }

    /**
     * 分销返利计算
     * @return
     */
    public Boolean distributionRebate(ProjectOrder projectOrder, List<UcDistributionType> ucDistributionTypes, ProjectDetail projectDetail) {
        UcUser ucUser = ucUserMapper.selectById(projectOrder.getUserId());
        if (StringUtils.isBlank(ucUser.getParentId())) {
            return true;
        }
        //先查出第一级分销人员
        UcUser oneUcUser = ucUserMapper.selectById(ucUser.getParentId());
        Boolean result = returnCommission(oneUcUser, projectOrder, TypeConstant.distributionLevelType.ONE, ucDistributionTypes, projectDetail);
        if (result && StringUtils.isNotBlank(oneUcUser.getParentId())) {
            List<UcUser> ucUserAll = ucUserMapper.selectList(null);
            List<String> ids = new ArrayList<>();
            ids.add(oneUcUser.getParentId());
            List<UcUser> ucUserList = reversalRecursionList(ucUserAll, ids);
            int size = ucUserList.size();
            if (size > 0) {
                for(int i = 0; i < size; i++) {
                    returnCommission(ucUserList.get(i), projectOrder, TypeConstant.distributionLevelType.MORE, ucDistributionTypes, projectDetail);
                }
            }

        }
        return true;
    }

    private Boolean returnCommission(UcUser ucUser, ProjectOrder projectOrder, String type,
                                     List<UcDistributionType> ucDistributionTypes, ProjectDetail projectDetail) {
        UcDistributionType ucDistributionType = CustomUtil.first(ucDistributionTypes, x  -> x.getId().equals(ucUser.getDistributionId()));
        BigDecimal ratio = BigDecimal.ZERO;
        if (type.equals(TypeConstant.distributionLevelType.MORE)) {
            ratio = ucDistributionType.getLevelRatio();
        }
        if (type.equals(TypeConstant.distributionLevelType.ONE)) {
            ratio = ucDistributionType.getDirectRatio();
        }
        //计算订单收益
        BigDecimal income = projectOrder.getAmount().multiply(projectOrder.getDailyInverse());
        BigDecimal amt = income.multiply(ratio).multiply(projectDetail.getCashRatio());
        BigDecimal integral = income.multiply(ratio).multiply(projectDetail.getIntegralRatio());
        UcRebateLog ucRebateLog = new UcRebateLog();
        ucRebateLog.setAmt(amt);
        ucRebateLog.setTxnSsn(CustomUtil.getSsn());
        ucRebateLog.setProjectId(projectOrder.getProjectId());
        ucRebateLog.setProjectOrderId(projectOrder.getId());
        ucRebateLog.setUserId(ucUser.getId());
        ucRebateLog.setType(TypeConstant.ucRebateType.DISTRIBUTION_REBATE);
        baseMapper.insert(ucRebateLog);

        InsertUsableParam insertUsableParam = new InsertUsableParam();
        insertUsableParam.setRemarks(ucRebateLog.getId());
        insertUsableParam.setUserId(ucUser.getId());
        insertUsableParam.setUsable(amt);
        insertUsableParam.setType(TypeConstant.usableChangeType.BALANCE_DISTRIBUTION_REBATE);
        ucAssetService.insertUsable(insertUsableParam);

        InsertIntegralParam insertIntegralParam = new InsertIntegralParam();
        insertIntegralParam.setRemarks(ucRebateLog.getId());
        insertIntegralParam.setType(TypeConstant.integralChangeType.INTEGRAL_DISTRIBUTION_REBATE);
        insertIntegralParam.setUserId(ucUser.getId());
        insertIntegralParam.setIntegral(integral);
        Boolean result = ucAssetService.insertIntegral(insertIntegralParam);

        UcUser orderUser = ucUserMapper.selectById(projectOrder.getUserId());
        UcDistributionLog ucDistributionLog = new UcDistributionLog();
        ucDistributionLog.setAmt(amt);
        ucDistributionLog.setIntegral(integral);
        ucDistributionLog.setProjectId(projectDetail.getId());
        ucDistributionLog.setProjectOrderId(projectOrder.getId());
        ucDistributionLog.setProjectType(projectDetail.getType());
        ucDistributionLog.setProjectName(projectDetail.getName());
        ucDistributionLog.setUserId(ucUser.getId());
        ucDistributionLog.setRemarks(ucRebateLog.getId());
        ucDistributionLog.setDistributionType(type);
        ucDistributionLog.setDistributorId(orderUser.getId());
        ucDistributionLog.setDistributorCode(orderUser.getCode());
        ucDistributionLog.setDistributorName(orderUser.getNickName());
        if (type.equals(TypeConstant.distributionLevelType.ONE)) {
            ucDistributionLog.setDirectSellingId(orderUser.getId());
        }
        distributionLogMapper.insert(ucDistributionLog);
        return result;
    }

    /**
     * 往上获取分销人员
     *
     * @param ucUsers 数据源
     * @param idList 标识集合
     * @return 数据列表
     */
    public  List<UcUser> reversalRecursionList(List<UcUser> ucUsers, List<String> idList) {
        //去重
        List<String> cidList = CustomUtil.distinct(idList);
        //获取idList中的用户
        List<UcUser> list = CustomUtil.where(ucUsers, x -> cidList.contains(x.getId()));
        // 获取上级
        List<String> pidList = CustomUtil.select(list, UcUser::getParentId);
        // 排除 已存在项 && 无效项
        pidList = CustomUtil.where(pidList, x -> StringUtils.isNotBlank(x) && !cidList.contains(x));
        if (pidList.size() > 0)
            list.addAll(reversalRecursionList(ucUsers, pidList));
        return list;
    }

    /**
     * 向下获取分销人员
     *
     * @param ucUserList 已有子项集合
     * @param idList 待查子项集合
     * @return 数据列表
     */
    @Override
    public  List<UcUser> childList(List<UcUser> ucUserList, List<String> idList) {
        //去重待查id
        List<String> cidList = CustomUtil.distinct(idList);
        //已有id集合
        List<String> ucUserIdList = CustomUtil.select(ucUserList, UcUser::getId);
        //查询子集
        QueryWrapper<UcUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("parent_id", cidList);
        List<UcUser> childList = ucUserMapper.selectList(queryWrapper);
        // 排除 已存在项 && 无效项
        childList = CustomUtil.where(childList, x -> Objects.nonNull(x) && !ucUserIdList.contains(x.getId()));
        if (childList.size() > 0) {
            //加入新查出的
            ucUserList.addAll(childList);
            //待查子项id
            List<String> childIdList = CustomUtil.select(childList, UcUser::getId);
            childList.addAll(childList(ucUserList, childIdList));
        }
        return ucUserList;
    }
}
